package com.example.demo.bizhan.thread;

import static java.lang.System.*;

/**
 * @description: xxx
 * @time: 2020-10-27 20:56
 * @author: baojinlong
 * 主线程获取子线程中的返回值
 * 1) 主线程等待
 * 2) 使用线程join方法来获取子线程返回值
 * 3) 使用Callable接口:FutureTask
 * 4) 使用线程池方式
 * 问题演示:多线程在操作共享数据或者是操作数据的线程代码有多行,如果有其它线程也参与了运算,就会导致安全问题.
 * 解决方案:synchronized枷锁,同一个时间点只有一个线程执行方法
 **/
public class ThreadDemo07 {
    public static void main(String[] args) {
        // method01();
        // method02();
        // method03();
        Example example = new Example();
        Runnable runnable1 = new TheThread(example);
        Runnable runnable2 = new TheThread(example);
        Thread thread1 = new Thread(runnable1);
        Thread thread2 = new Thread(runnable2);
        thread1.start();
        thread2.start();

    }

    private static void method03() {
        Example example = new Example();
        // 访问同一个对象的时候只要上锁了.其它同步方法也是按照顺序来执行的
        Runnable runnable1 = new TheThread(example);
        Runnable runnable2 = new TheThread2(example);
        Thread thread1 = new Thread(runnable1);
        Thread thread2 = new Thread(runnable2);
        thread1.start();
        thread2.start();
    }

    private static void method02() {
        Runnable runnable1 = new TheThread(new Example());
        Runnable runnable2 = new TheThread(new Example());
        Thread thread1 = new Thread(runnable1);
        Thread thread2 = new Thread(runnable2);
        thread1.start();
        thread2.start();
    }

    private static void method01() {
        Example example = new Example();
        Runnable runnable = new TheThread(example);
        Thread thread1 = new Thread(runnable);
        Thread thread2 = new Thread(runnable);
        thread1.start();
        thread2.start();
    }

}

// synchronized修饰的普通方式是对对象加锁,修饰的static的方法就是对类进行加锁
class Example {
    // 如果去掉则不是按照01线程的顺序来访问的
    public synchronized static void execute() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                out.println("出现异常");
                Thread.currentThread().interrupt();
            }
            out.println(Thread.currentThread().getName() + " Example.execute: " + i);
        }
    }

    public synchronized void execute2() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                out.println("出现异常");
                Thread.currentThread().interrupt();
            }
            out.println(Thread.currentThread().getName() + " Example.execute: " + i);
        }
    }

    public void execute3() {
        for (int i = 0; i < 10; i++) {
            synchronized ((this)) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            out.println(Thread.currentThread().getName() + " Example.execute: " + i);
        }
    }
}

class TheThread implements Runnable {
    private Example example;

    public TheThread(Example example) {
        this.example = example;
    }

    @Override
    public void run() {
        example.execute();
    }
}

class TheThread2 implements Runnable {
    private Example example;

    public TheThread2(Example example) {
        this.example = example;
    }

    @Override
    public void run() {
        example.execute2();
    }
}